﻿#region

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

using Pob.CustomEventArgs;
using Pob.GameObjects;
using Pob.GameObjects.PowerUps.General;

#endregion

namespace Pob.ScreenManagement.GameScreens
{
    public delegate void GameScreenEvent(object sender, GameScreenEventArgs args);

    public class GameScreen : ScreenBase
    {
        #region Fields

        private readonly List<GameComponent> _balls;

        private readonly List<GameComponent> _collisionObjects;

        private readonly PowerUpCreator _powerUpCreator;

        private readonly RoundManager _roundManager;

        #endregion

        #region Constructors and Destructors

        public GameScreen(Game game, GameScreenEvent eventHandler)
            : base(game)
        {
            Background = new Background(game, "GameBack", new Vector2(0, 0), 1, Color.White);

            _balls = new List<GameComponent>
                {
                    new Ball(game, "Ball", new Vector2(Settings.Width / 2f, (Settings.Height / 2f) + (Settings.Height / 20f)), 0.3f, 0, new Vector2(1, 0), 0, PointScored), 
                };

            _roundManager = new RoundManager(game, this);

            _powerUpCreator = new PowerUpCreator(game, this);

            _collisionObjects = new List<GameComponent>
                {
                    new Paddle(game, "Paddle", new Vector2(20f, Settings.Height / 2f), 1, _roundManager.Player1), 
                    new Paddle(game, "Paddle", new Vector2(Settings.Width - 30f, Settings.Height / 2f), 1, _roundManager.Player2), 
                    new Endzone(game, "EndClear", new Vector2(Settings.Width - 15f, 80), 1, 0, _roundManager.Player1, false), 
                    new Endzone(game, "End", new Vector2(0, 80), 1, 0, _roundManager.Player2, true), 
                    new Bande(game, "BandeTop", new Vector2(0, 70), 1, 0), 
                    new Bande(game, "Bande", new Vector2(0, Settings.Height - 15f), 1, 0)
                };

            FpsCounter = new FpsCounter(game, GameContent.FontFpsCounter);

            GamePaused += eventHandler;
            GameOver += eventHandler;

            MyComponents.Add(Background);
            MyComponents.AddRange(_balls);
            MyComponents.AddRange(_collisionObjects);
            MyComponents.Add(_roundManager);
            MyComponents.Add(_powerUpCreator);
        }

        #endregion

        #region Public Events

        public event GameScreenEvent GameOver;

        public event GameScreenEvent GamePaused;

        #endregion

        #region Public Methods and Operators

        public override void Initialize()
        {
            _roundManager.Activate();
            AddRange(MyComponents);

            ComponentAdded += AddToComponents;
            ComponentRemoved += RemoveFromComponents;

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            if (_roundManager.RoundTime < 0)
            {
                _powerUpCreator.Enabled = false;
            }
            else
            {
                if (_roundManager.RoundTime > 2)
                {
                    _powerUpCreator.Enabled = true;
                }

                GetInput();

                foreach (Ball ball in _balls)
                {
                    foreach (GameObject collisionObject in
                        _collisionObjects)
                    {
                        if (ball.CheckKollision(collisionObject))
                        {
                            ball.UpdateAfterKollision(collisionObject);
                        }
                    }

                    foreach (Ball ball1 in _balls)
                    {
                        foreach (Ball ball2 in _balls)
                        {
                            if (ball1.CheckKollision(ball2) && !ball1.Equals(ball2))
                            {
                                ball.UpdateAfterKollision(ball2);
                            }
                        }
                    }

                    foreach (Ball ball1 in _balls)
                    {
                        if (ball1.CheckKollision(_powerUpCreator.DisplayedPowerUp))
                        {
                            ball.UpdateAfterKollision(_powerUpCreator.DisplayedPowerUp);
                        }
                    }

                    if (Math.Floor(_roundManager.RoundTime) % 10 == 0)
                    {
                        ball.IncreaseSpeed(gameTime);
                    }
                }
            }
        }

        #endregion

        #region Methods

        protected virtual void OnGameOver(Player winner)
        {
            var args = new GameScreenEventArgs(winner, GameState.Over);

            if (GameOver != null)
            {
                GameOver(this, args);
            }
        }

        protected virtual void OnGamePaused()
        {
            var args = new GameScreenEventArgs(null, GameState.Paused);

            if (GamePaused != null)
            {
                GamePaused(this, args);
            }
        }

        private void GetInput()
        {
            KeyboardState key = Keyboard.GetState();

            if (key.IsKeyDown(Keys.Escape))
            {
                OnGamePaused();
            }
        }

        private void PointScored(object sender, PointScoredEventArgs args)
        {
            _roundManager.StartNewRound();

            _powerUpCreator.Reset();

            if (args.GameEnds)
            {
                OnGameOver(args.Scorer);
            }
        }

        private void AddToComponents()
        {
            Add(MyComponents[MyComponents.Count - 1]);
        }

        private void RemoveFromComponents(GameComponent component)
        {
            Remove(component);
        }

        #endregion
    }
}